Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Platform compatibility analyzer draft #3

Closed
wants to merge 19 commits into from
Closed

Conversation

buyaa-n
Copy link
Owner

@buyaa-n buyaa-n commented Jul 7, 2020

Related design doc https://github.com/dotnet/designs/blob/master/accepted/2020/platform-checks/platform-checks.md

Related issue dotnet/runtime#37359 (It need to be updated with latest API review changes)

src/Test.Utilities/CSharpCodeFixVerifier`2.cs Outdated Show resolved Hide resolved
}

[Fact]
public async Task WrongPlatformStringsShouldHandledGracefully()

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm trying to understand this test: Why do invalid strings still trigger the rule?

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good question, the purpose of this analyzer is not reporting the wrong string values, the purpose of this test is to check if the analyzer would crush or throw any unhandled exceptions with any different/wrong OS platform string values

{
var typeName = WellKnownTypeNames.SystemRuntimeInteropServicesRuntimeInformation;

if (!context.Compilation.TryGetOrCreateTypeByMetadataName(typeName + "Helper", out var runtimeInformationType))
Copy link
Owner Author

@buyaa-n buyaa-n Jul 21, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When we are able to consume the new APIs this mock class load will be removed

return;
}

if (guardMethods.IsEmpty || !(context.OperationBlocks.GetControlFlowGraph() is { } cfg))
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

guardMethods are new API so if it does not exist in the current compilation no need to do flow analysis, just report diagnostic for all methods in platformSpecificOperations dictionary

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

guardMethods are new API so if it does not exist in the current compilation

Right, but we could have bailed much earlier, no?

Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't we want to warn on builds not having those methods?

@terrajobst
Copy link

terrajobst commented Jul 22, 2020

I've pulled down your PR and played with the analyzer. My feedback is below. I can file them as individual bugs as well.

Constructors aren't warned

Repro:

class Program
{
    static void Main(string[] args)
    {
        var x = new WindowsOnlyAPI();
        Console.WriteLine("Hello World!");
    }
}

[MinimumOSPlatform("win7.0")]
class WindowsOnlyAPI
{
}

Actual:

No diagnostic

Expected:

CA1416: 'WindowsOnlyAPI' requires win 7.0 version or later.

Analyzer should also handle IsOSPlatform

While IsOSPlatform doesn't include version information, it should use those checks to infer reachability for a platform in version 0.0.

Repro:

class Program
{
    static void Main(string[] args)
    {
        if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
            return;

        WindowsOnlyAPI.Test();
    }
}

[MinimumOSPlatform("win7.0")]
static class WindowsOnlyAPI
{
    public static void Test()
    {
    }
}

Actual:

CA1416: 'Test' requires win 7.0 version or later.

Expected:

No diagnostic

Incorrect version numbers are ignored

Repro:

class Program
{
    static void Main(string[] args)
    {
        if (!RuntimeInformation.IsOSPlatformOrLater("win7"))
            return;

        WindowsOnlyApi();
    }

    [MinimumOSPlatform("win7.0")]
    static void WindowsOnlyApi()
    {

    }
}

Actual:

CA1416: 'WindowsOnlyApi' requires win 7.0 version or later.

Expected:

Either infer that "win7" is "win7.0" or warn that "win7" isn't valid.

Logical or isn't handled properly

Repro:

class Program
{
    static void Main(string[] args)
    {
        if (RuntimeInformation.IsOSPlatformOrLater("win7.0") ||
            RuntimeInformation.IsOSPlatformOrLater("win7.1"))
        {
            WindowsOnlyApi();
        }
    }

    [MinimumOSPlatform("win7.0")]
    static void WindowsOnlyApi()
    {
    }
}

Actual:

CA1416: 'WindowsOnlyApi' requires win 7.0 version or later.

Expected:

No diagnostic

Feature: Handle OSVersion for Windows

We should consider special casing Windows (and maybe Unix) to also allow platform checks via the old Environment.OSVersion API.

Repro:

class Program
{
    static void Main(string[] args)
    {
        if (Environment.OSVersion.Platform == PlatformID.Win32NT &&
            Environment.OSVersion.Version >= new Version(7, 0))
        {
            WindowsOnlyApi();
        }
    }

    [MinimumOSPlatform("win7.0")]
    static void WindowsOnlyApi()
    {
    }
}

Actual:

CA1416: 'WindowsOnlyApi' requires win 7.0 version or later.

Expected:

No diagnostic

Local functions aren't processed

Repro:

class Program
{
    static void Main(string[] args)
    {
        void Test()
        {
            WindowsOnlyApi();
        }

        Test();
    }

    [MinimumOSPlatform("win7.0")]
    static void WindowsOnlyApi()
    {
    }
}

Actual:

No diagnostics

Expected:

CA1416: 'WindowsOnlyApi' requires win 7.0 version or later.

Copy link

@terrajobst terrajobst left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should remove the TFM logic. The rest is just minor suggestions.

return;
}

if (guardMethods.IsEmpty || !(context.OperationBlocks.GetControlFlowGraph() is { } cfg))

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

guardMethods are new API so if it does not exist in the current compilation

Right, but we could have bailed much earlier, no?

@buyaa-n
Copy link
Owner Author

buyaa-n commented Jul 22, 2020

I've pulled down your PR and played with the analyzer. My feedback is below. I can file them as individual bugs as well.

Those are really interesting/good scenarios, thanks!

description: s_localizableObsoleteMessage,
isPortedFxCopRule: false,
isDataflowRule: false);
internal static DiagnosticDescriptor RemovedRule = DiagnosticDescriptorHelper.Create(RuleId,
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@terrajobst @jeffhandley as i mentioned in the morning the Obsolete and Removed rules are work same as MinimumOS rule, i.e. if Obsolete attribute defined for an API then that API is restricted to only for that Platform. For now, i am gonna leave this implementation as is as we haven no any Obsolete/Removed attributes added into any API. The fix will come with the functionality update for the Unsupported attributes.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the heads-up, @buyaa-n. For Preview 8, that sounds good to me. We'll then change the behavior in RC1 with the other changes.

@buyaa-n buyaa-n closed this Aug 7, 2020
@buyaa-n buyaa-n deleted the plat_spec_an branch August 7, 2020 21:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants